package com.lazy.app.service;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Notification;
import android.app.Service;
import android.content.ContentValues;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.Image;
import android.media.ImageReader;
import android.media.MediaActionSound;
import android.media.MediaScannerConnection;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.IBinder;
import android.os.SystemClock;
import android.provider.MediaStore;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationChannelCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;

import com.zndroid.utils.XUtils;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

/**
 * 从 Android 11 开始，应用无法在外部存储设备上创建自己的应用专用目录。如需访问系统为您的应用提供的目录，请调用 getExternalFilesDirs()。
 * 注意：当您将应用更新为以 Android 11（API 级别 30）为目标平台后，如果应用在搭载 Android 11 的设备上运行，
 * 系统会忽略 requestLegacyExternalStorage 属性.
 * @author lazy
 * */
@RequiresApi(api = Build.VERSION_CODES.Q)
public class ScreenShotService extends Service {
    public static final String KEY_DATA = "data";

    private int screenWidth;
    private int screenHeight;
    private int density;

    private MediaActionSound mediaActionSound;
    private MediaProjectionManager mediaProjectionManager;
    private MediaScannerConnection mediaScannerConnection;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        screenWidth = XUtils.create().screenUtil().getScreenWidth(this);
        screenHeight = XUtils.create().screenUtil().getScreenHeight(this);
        density = (int) XUtils.create().screenUtil().getDensity(this);

        mediaActionSound = new MediaActionSound();
        mediaActionSound.load(MediaActionSound.SHUTTER_CLICK);

        mediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);

        createNotificationChannel();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        MediaProjection mediaProjection = mediaProjectionManager.getMediaProjection(Activity.RESULT_OK, intent.getParcelableExtra(KEY_DATA));
        createScreenShot(mediaProjection);
        return super.onStartCommand(intent, flags, startId);
    }

    private void createScreenShot(MediaProjection mediaProjection) {
        @SuppressLint("WrongConstant")
        final ImageReader imageReader = ImageReader.newInstance(
                screenWidth,
                screenHeight,
                PixelFormat.RGBA_8888,
                1);
        VirtualDisplay virtualDisplay = mediaProjection.createVirtualDisplay(
                "capture",
                screenWidth,
                screenHeight,
                density,
                DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
                imageReader.getSurface(),
                null,
                null);
        imageReader.setOnImageAvailableListener(reader -> {
            mediaActionSound.play(MediaActionSound.SHUTTER_CLICK);

            //截图有一定的时间差
            SystemClock.sleep(500);

            Image image = reader.acquireLatestImage();
            if (null != image) {
                Image.Plane[] planes = image.getPlanes();
                ByteBuffer buffer = planes[0].getBuffer();
                int pixelStride = planes[0].getPixelStride();
                int rowStride = planes[0].getRowStride();
                int rowPadding = rowStride - pixelStride * screenWidth;

                Bitmap bitmap = Bitmap.createBitmap(screenWidth + rowPadding / pixelStride,
                        screenHeight, Bitmap.Config.ARGB_8888);
                bitmap.copyPixelsFromBuffer(buffer);

                image.close();
                imageReader.close();
                mediaProjection.stop();
                virtualDisplay.release();

                saveByAPI29(bitmap);
            }
        }, null);
    }

    @SuppressWarnings("deprecation")
    @RequiresApi(api = Build.VERSION_CODES.Q)
    private void saveByAPI29(Bitmap bitmap) {
        long time = System.currentTimeMillis();
        String imageDate = new SimpleDateFormat("yyyyMMdd-HH-mm-ss", Locale.getDefault()).format(new Date(time));
        String fileName = String.format("Dev_Screenshot_%s.png", imageDate);
        //如果将照片保存到 getExternalFilesDir() 提供的目录中，媒体扫描器将无法访问相应的文件，因为这些文件对您的应用保持私有状态
        String dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath() + File.separator + "Screenshots";

        XUtils.create().fileUtil().createDirs(dir);
        File picFile = new File(dir, fileName);

        //公有目录进行持久化
        Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;

        ContentValues contentValues = new ContentValues();
        contentValues.put(MediaStore.Images.Media.TITLE, fileName);
        contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, fileName);
        contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/png");
        contentValues.put(MediaStore.Images.Media.DATE_ADDED, time);
        contentValues.put(MediaStore.Images.Media.HEIGHT, bitmap.getHeight());
        contentValues.put(MediaStore.Images.Media.WIDTH, bitmap.getWidth());
        contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_DCIM + File.separator + "Screenshots");

//        如果您的应用执行可能非常耗时的操作（例如写入媒体文件），那么在处理文件时对其进行独占访问非常有用。
//        在搭载 Android 10 或更高版本的设备上，您的应用可以通过将 IS_PENDING 标记的值设为 1 来获取此独占访问权限。
//        如此一来，只有您的应用可以查看该文件，直到您的应用将 IS_PENDING 的值改回 0。
        contentValues.put(MediaStore.Images.Media.IS_PENDING, 0);

        Uri imageUri = getContentResolver().insert(uri, contentValues);
        if (null != imageUri) {
            OutputStream os = null;
            try {
                os = getContentResolver().openOutputStream(imageUri);
                if (null != os) {
                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, os);
                    os.flush();

                    Toast.makeText(this, "截图成功", Toast.LENGTH_SHORT).show();
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                bitmap.recycle();

                try {
                    if (os != null) {
                        os.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            //通知刷新相册
            updateMedia(picFile.getAbsolutePath());
        }

    }

    private void updateMedia(String path) {
        mediaScannerConnection = new MediaScannerConnection(this, new MediaScannerConnection.MediaScannerConnectionClient() {
            @Override
            public void onMediaScannerConnected() {
                mediaScannerConnection.scanFile(path, "image/png");
            }

            @Override
            public void onScanCompleted(String path, Uri uri) {
                mediaScannerConnection.disconnect();
                stopSelf();
            }
        });

        if (!mediaScannerConnection.isConnected()) {
            mediaScannerConnection.connect();
        }
    }

    private void createNotificationChannel() {
        int notifyId = 21121;
        String channelId = "screen_shot_notification";
        String channelName = getPackageName();

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, channelId);
        builder.setSmallIcon(getApplicationInfo().icon);
        builder.setPriority(NotificationCompat.PRIORITY_DEFAULT);
        builder.setStyle(new NotificationCompat
                .BigTextStyle()
                .setBigContentTitle(getApplicationInfo().name)
                .setSummaryText("截图中..."));

        NotificationChannelCompat notificationChannelCompat = new NotificationChannelCompat.Builder(channelId, NotificationManagerCompat.IMPORTANCE_DEFAULT)
                //必须设置 否则：java.lang.IllegalArgumentException
                .setName(channelName)
                .build();

        NotificationManagerCompat.from(this).createNotificationChannel(notificationChannelCompat);

        Notification notification = builder.build();

        startForeground(notifyId, notification);
    }
}
